import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @description: 自定义线程池
 * @author: zys
 * @create: 2020-10-22 15:59
 **/
public class TestThreadPool {

    public static void main(String[] args) {

        /**线程池
         * @param corePoolSize     核心池大小 int
         * @param maximumPoolSize  最大池大小 int
         * @param keepAliveTime    保活时间   long（任务完成后要销毁的延时）
         * @param unit             时间单位    决定参数3的单位，枚举类型的时间单位
         * @param workQueue        工作队列    用于存储任务的工作队列（BlockingQueue接口类型）
         * @param threadFactory    线程工厂    用于创建线程
         */
        // 参数任务上限
        LinkedBlockingQueue<Runnable> blockingQueue = new LinkedBlockingQueue<>(100);
        ThreadFactory threadFactory = new ThreadFactory() {
            //  int i = 0;  用并发安全的包装类
            AtomicInteger atomicInteger = new AtomicInteger(1);

            @Override
            public Thread newThread(Runnable r) {
                //创建线程 将任务传进来
                Thread thread = new Thread(r);
                // 线程命名
                thread.setName("MyThread" + atomicInteger.getAndIncrement());
                return thread;
            }
        };
        ThreadPoolExecutor pool = new ThreadPoolExecutor(10, 20, 1, TimeUnit.SECONDS, blockingQueue, threadFactory);

        // 设置任务丢弃后的处理策略
        // AbortPolicy该策略是线程池的默认策略 使用该策略时，如果线程池队列满了丢掉这个任务并且抛出RejectedExecutionException异常
        // DiscardPolicy 策略，如果线程池队列满了，会直接丢掉这个任务并且不会有任何异常。
        // DiscardOldestPolicy 也就是说如果队列满了，会将最早进入队列的任务删掉腾出空间，再尝试加入队列。
        //CallerRunsPolicy 使用此策略，如果添加到线程池失败，那么主线程会自己去执行该任务，不会等待线程池中的线程去执行。
        //还可以进行自定义策略 消息队列 redis kafka等
        pool.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        for (int i = 0; i < 100; i++) {
            pool.execute(new Runnable() {
                @Override
                public void run() {
                    try {
                        method();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            });
        }
    }

    private static void method() throws InterruptedException {
        System.out.println("ThreadName" + Thread.currentThread().getName() + "进来了");
        Thread.sleep(2000);
        System.out.println("ThreadName" + Thread.currentThread().getName() + "出去了");
    }

}
